package game.util;

import game.ChancePair;
import game.Constants;

import java.text.DateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;

public class Util {
	private static Random random = new Random();

	public static void SetRandomSeed(long seed) {
		random = new Random(seed);
	}

	public static String GetRandomString(List<String> values) {
		String[] array = (String[]) values.toArray();
		return GetRandomString(array);
	}

	public static String GetRandomString(String[] values) {
		int index = random.nextInt(values.length);
		return values[index];
	}

	public static Enum<?> GetRandomEnumValue(Enum<?>[] enumValues) {
		List<Enum<?>> values = Collections.unmodifiableList(Arrays
				.asList(enumValues));
		return values.get(random.nextInt(values.size()));
	}

	public static <T> T GetRandomListValue(List<T> list) {
		T value = null;
		if (!list.isEmpty()) {
			int index = GetRandomIntBetween(0, list.size() - 1);
			value = list.get(index);
		}
		if (value != null)
			return value;
		else
			throw new IllegalStateException("Null value picked");
	}

	public static <T> T GetRandomFromChancePair(
			Collection<ChancePair<T>> chancePairs) {
		final int random = GetRandomIntBetween(1, 100);

		int base = 0;
		for (ChancePair<T> pair : chancePairs) {
			int chance = pair.getChance();
			if (random <= chance + base)
				return pair.getValue();
			base += chance;
		}
		return null;
	}

	/**
	 * return's bValue mapped onto a via Linear Interpolation.
	 * 
	 * @param aMax
	 * @param aMin
	 * @param bMax
	 * @param bMin
	 * @param bValue
	 * @return
	 */
	public static long LinearInterpolate(long aMax, long aMin, long bMax,
			long bMin, long bValue) {
		long aRange = aMax - aMin;
		long bRange = bMax - bMin;
		long bDiff = bValue - bMin;
		return aMin + bDiff * (aRange / bRange);
	}

	/**
	 * Returns the value bounded between the upper and lower
	 * 
	 * @param upper
	 * @param lower
	 * @param value
	 * @return
	 */
	public static int GetBoundedValue(int upper, int lower, int value) {
		value = Math.max(lower, value);
		value = Math.min(upper, value);
		return value;
	}

	/**
	 * Generates a random number from minimum to maximum (inclusive)
	 * 
	 * @param minimum
	 * @param maximum
	 * @return
	 */
	public static int GetRandomIntBetween(int minimum, int maximum) {
		return random.nextInt(maximum - minimum + 1) + minimum;
	}

	public static void log(String text) {
		if (Constants.DEBUG) {
			String logText = "[" + getShortDate(new Date()) + "] " + text;
			print(logText);
		}
	}

	public static Date getFutureDate(long inFuture) {
		Date now = new Date();
		return new Date(now.getTime() + inFuture);
	}

	public static String getShortDate(Date date) {
		return DateFormat.getTimeInstance().format(date);
	}

	/**
	 * Prints the given text to console (ghetto word wrapped)
	 * 
	 * @param text
	 */
	public static void print(String text) {
		if (Constants.DEBUG) {
			String textBuffer = text;
			// While unprinted text remains
			while (!textBuffer.isEmpty()) {
				int newLineIndex = textBuffer.indexOf("\n");
				int length = textBuffer.length();

				if ((newLineIndex > Constants.LINE_WRAP)
						|| (newLineIndex == -1 && length > Constants.LINE_WRAP)) {
					int newEnd = Constants.LINE_WRAP;
					while (newEnd > 0
							&& !Character.isWhitespace(textBuffer
									.charAt(newEnd)))
						newEnd--;
					System.out.print(textBuffer.substring(0, newEnd) + "\n");
					textBuffer = textBuffer.substring(newEnd + 1, length);
				} else if (newLineIndex < Constants.LINE_WRAP
						&& newLineIndex > 0) {
					System.out.print(textBuffer.substring(0, newLineIndex));
					textBuffer = textBuffer.substring(newLineIndex, length);
				} else {
					System.out.print(textBuffer);
					textBuffer = "";
				}
			}
		}
	}
}
